// ignore: implementation_imports, import_of_legacy_library_into_null_safe
import 'package:build/src/builder/build_step.dart';
import 'package:analyzer/dart/element/element.dart' as ele;

// ignore: import_of_legacy_library_into_null_safe
import 'package:source_gen/source_gen.dart';

// ignore: import_of_legacy_library_into_null_safe
import 'package:build/build.dart';
import 'package:xanno/src/anno/utils/pars_params.dart';
import 'dart:io';
import 'tpl/tpl.dart' as tpl;
import 'assets.dart';

class AssetsGenerator extends GeneratorForAnnotation<GAssets> {
  final separator = Platform.pathSeparator;
  final List<String> assetsList = [];
  List ignores = [
//    '.json',
    '.ttf',
    '.DS_Store',
  ];

  String buildAssets(list) {
    var sb = StringBuffer();
    list.forEach((value) {
      sb.writeln("    - $value");
    });
    return sb.toString();
  }

  String buildCode(List<String> list, String assetsPath) {
    var sb = StringBuffer();
    var map = Map<String, int>();
    list
        .map((e) {
          return e.replaceFirst(
              RegExp("$assetsPath/\\d+(\\.)?(\\d+)?x/"), "$assetsPath/");
        })
        .toSet()
        .forEach((value) {
          List<String> arr = value.split('/');
          arr.removeAt(0);
          arr[arr.length - 1] = arr[arr.length - 1].split('.').first;
          var key = arr.join('_');
          if (map.containsKey(key)) {
            map[key] = map[key]! + 1;
            sb.writeln("  static const String ${key}_${map[key]} = '$value';");
          } else {
            map[key] = 0;
            sb.writeln("  static const String $key = '$value';");
          }
        });
    return sb.toString();
  }

  String readPubspec(String path, List list, assetsPath) {
    var sb = StringBuffer();
    try {
      List<String> lines = File(path).readAsLinesSync();
      if (list.isEmpty) {
        return File(path).readAsStringSync();
      }
      bool one = true;
      lines.forEach((v) {
        if (v.indexOf(RegExp(r".*assets:")) >= 0 && one) {
          one = false;
          sb.writeln('  assets:');
          sb.writeln(buildAssets(list));
        } else {
          var nv =
              v.replaceAll(RegExp("((.*- $assetsPath/(.*))|(.*assets:))"), "");
          if (nv.trim().length > 0) {
            sb.writeln(nv);
          }
        }
      });
      return sb.toString();
    } catch (e) {
      stdout.writeln('文件读取失败! $e');
    }
    return sb.toString();
  }

  void readFiles(String path, String package) {
    try {
      Directory(path).listSync().forEach((f) {
        var bool = FileSystemEntity.isFileSync(f.path);
        if (bool) {
          String filePath = f.path.split('/$package/').last;

          ///忽略自动生成代码
          var ignoreItem;
          try {
            ignoreItem =
                ignores.firstWhere((element) => f.path.endsWith(element));
          } catch (e) {}
          if (ignoreItem == null) {
            assetsList.add(filePath);
          }
        } else {
          readFiles(f.path, package);
        }
      });
    } catch (e) {
      stdout.writeln('目录不存在! $e');
    }
  }

  @override
  generateForAnnotatedElement(
      ele.Element element, ConstantReader annotation, BuildStep buildStep) {
    final map = ParsParams.pars(annotation,
        {'enable': false, 'path': '', 'dir': '', 'name': '', 'suffix': ''});
    bool enable = map['enable'];
    String path = map['path'];
    String dir = map['dir'];
    String name = map['name'];
    String suffix = map['suffix'];
    if (!enable) return null;
    if (path.length <= 0) return null;

    String fileDir = dir.split('/').join(separator);
    String fileName = '$separator$name';

    Directory('${Directory.current.path}$separator$path')
        .createSync(recursive: true);
    readFiles(
        '${Directory.current.path}$separator$path', buildStep.inputId.package);

    File('${Directory.current.path}${separator}pubspec.yaml').writeAsStringSync(
        readPubspec('${Directory.current.path}${separator}pubspec.yaml',
            assetsList, path));

    File('${Directory.current.path}$separator$fileDir$fileName$suffix')
      ..createSync(recursive: true)
      ..writeAsStringSync(tpl.clazzTpl(buildCode: buildCode(assetsList, path)));
    return null;
  }
}

Builder assetsBuilder(BuilderOptions options) =>
    LibraryBuilder(AssetsGenerator(), generatedExtension: ".assets.dart");
